const Environment = require('yeoman-environment')
const logger = require('./logger')
const path = require('path')
const fs = require('fs')
const chalk = require('chalk')

const done = err => {
  if (err instanceof Error) {
    logger.error(`ERROR! ${err.message}`, err);
  } else if (err) {
    logger.error(`ERROR! ${err}`);
  } else {
    logger.info(chalk.green.bold('Generate Success !'));
  }
}

module.exports = class {
  constructor() {
    this.env = Environment.createEnv()
  }

  init(program) {
    this.env.lookup({ packagePaths: [path.resolve(__dirname, '..')] }).forEach(generator => {
      this.loadGeneratorCommands(generator, program)
    })
  }

  loadGeneratorCommands(generator, program) {
    let namespace = generator.namespace

    let cmdPath = path.join(path.dirname(generator.generatorPath), 'commands.js')
    try {
      let stats = fs.statSync(cmdPath)
      if (!stats.isFile()) {
        return
      }
      let { cmd, options, desc, help } = require(path.relative(__dirname, cmdPath))
      let command = program.command(cmd).allowUnknownOption()

      options && options.forEach(item => command.option(...item))

      desc && command.description(desc)

      command.action((...params) => {
        this.runGenerator(program, namespace, params)
      })

      help && command.on('--help', () => {
        logger.log(`\nHelp:\n${help}`)
      })
    } catch (error) {
      // logger.debug(`${cmdPath} not exit`)
    }
  }


  runGenerator(program, namespace, params) {
    let args, options, cmdObj = params.pop();

    if (Array.isArray(cmdObj)) {
      cmdObj = params.pop()
    }

    options = {
      ...program.opts(),
      ...cmdObj.opts()
    }

    args = cmdObj.args

    try {
      this.env.run([namespace, ...args], options).then(done)
    } catch (error) {
      logger.error(`ERROR! ${error.message}`, error)
    }
  }
}